/**
 * 
 */
package edu.umd.clip.lm.factors;

import java.util.*;
import java.io.*;
import java.util.regex.*;
/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
abstract public class InputParser {
	private long[] startTuples = null;
	private long[] endTuples = null;
	private char escapeChar = '\\';
	private final static Pattern defaultWordSeparator = Pattern.compile("\\s+");
	protected FactorTupleDescription tupleDescription;
	
	public InputParser(FactorTupleDescription desc) {
		tupleDescription = desc;
	}
	
	public long[] parseSentence(String sentence) {
		sentence = sentence.trim();
		String[] words = splitLine(sentence);
		int size = words.length;
		if (size == 0) return new long[0];
		if (startTuples != null) size += startTuples.length;
		if (endTuples != null) size += endTuples.length;
		
		long[] output = new long[size];
		int pos = 0;
		if (startTuples != null) {
			for(long tuple : startTuples) {
				output[pos++] = tuple;
			}
		}
		for(String word : words) {
			output[pos++] = Dictionary.isEndWord(word) ? tupleDescription.createEndTuple() : wordToTuple(word);
		}
		if (endTuples != null) {
			for(long tuple : endTuples) {
				output[pos++] = tuple;
			}
		}
		return output;
	}
	
	@SuppressWarnings("unused")
	public ArrayList<String> parseSentenceToWords(String sentence) {
		sentence = sentence.trim();
		String[] words = splitLine(sentence);
		int size = words.length;
		if (size == 0) return new ArrayList<String>(0);
		if (startTuples != null) size += startTuples.length;
		if (endTuples != null) size += endTuples.length;
		
		ArrayList<String> output = new ArrayList<String>(size);
		if (startTuples != null) {
			for(long tuple : startTuples) {
				output.add(Dictionary.getStartWord());
			}
		}
		for(String word : words) {
			output.add(tupleWordToSurfaceWord(word));
		}
		if (endTuples != null) {
			for(long tuple : endTuples) {
				output.add(Dictionary.getEndWord());
			}
		}
		return output;
	}
	
	public List<long[]> parseInput(BufferedReader input) throws IOException {
		LinkedList<long[]> output = new LinkedList<long[]>();
	
		for(String line = input.readLine(); line != null; ) {
			output.add(parseSentence(line));
		}
		return output;
	}
	
	public List<ArrayList<String>> parseInputToWords(BufferedReader input) throws IOException {
		LinkedList<ArrayList<String>> output = new LinkedList<ArrayList<String>>();
	
		for(String line = input.readLine(); line != null; ) {
			output.add(parseSentenceToWords(line));
		}
		return output;
	}
	
	public static String[] splitLine(String line) {
		return defaultWordSeparator.split(line);
	}
	
	abstract public long wordToTuple(String word);
	abstract public String tupleToWord(long tuple);
	// converts "W-the:T-DT" to "the" to recover surface form of unknown words
	abstract public String tupleWordToSurfaceWord(String word);
	
	public long[] getStartTuples() {
		return startTuples;
	}
	public void setStartTuples(long[] startTuples) {
		this.startTuples = startTuples;
	}
	public long[] getEndTuples() {
		return endTuples;
	}
	public void setEndTuples(long[] endTuples) {
		this.endTuples = endTuples;
	}
	public char getEscapeChar() {
		return escapeChar;
	}
	public void setEscapeChar(char escapeChar) {
		this.escapeChar = escapeChar;
	}
}
